#coding=utf-8
'''
Created on 2013年8月30日

@author: xuben
'''
import Logger
import PushCommand
import json
import socket
import struct
import zlib

'''
根据域名获取ip地址
'''
def getIp(domain):
    ip = ""
    if domain.find('http://') >= 0:
        ip = socket.gethostbyname(domain[len('http://'):])
#         ip = socket.getaddrinfo(domain[len('http://'):], 'http')[0][4][0]
    return ip

#socket状态-非连接
SOCKET_STATE_NOT_CONNECTED = 0
#socket状态-连接
SOCKET_STATE_CONNECTED = 1
#socket状态-重连
SOCKET_STATE_RECONNECTED = 2

class SocketService:

    #socket客户端
    client = socket.socket()
    #状态
    state = SOCKET_STATE_NOT_CONNECTED
    #服务端地址
    addr = None
    #请求id
    requestId = 0
    #请求对应的回调函数
    callbacks = {}

    '''
            建立连接
    '''
    def connect(self, addr):
        self.addr = addr
        try:
            self.client.connect(addr)
            self.state = SOCKET_STATE_CONNECTED
        except socket.error, e:
            Logger.log(e.message, Logger.LOGGER_ERROR, True)

    '''
            断开连接
    '''
    def close(self):
        self.client.close()

    '''
            重连
    '''
    def reconnect(self):
        try:
            self.client.close()
            self.client = socket.socket()
            self.client.connect(self.addr)
            self.state = SOCKET_STATE_CONNECTED
        except socket.error, e:
            Logger.log(e.message, Logger.LOGGER_ERROR, True)

    '''
            发送请求
    '''
    def send(self, command, params, callback=None):
        self.requestId += 1
        if callback != None:
            self.callbacks[self.requestId] = callback
        data = struct.pack('>i32si' + str(len(params)) + 's', 4 + 32 + len(params), command, self.requestId, params)
        try:
            self.client.send(data)
        except socket.error, e:
            Logger.log(e.message, Logger.LOGGER_ERROR, True)
#             print 'send:', e
    
    '''
            接收数据
    '''
    def receive(self):
        raw_binary_data = self.receiveData(40)
        if len(raw_binary_data) < 40:
            return False
        raw_format = struct.Struct('>i32si')
        raw_data = raw_format.unpack_from(raw_binary_data)
#         print raw_data
    
        content_data_length = raw_data[0] - 4 - 32
        content_binary_data = self.receiveData(content_data_length)
        if len(content_binary_data) < content_data_length:
            return False
        content_format = struct.Struct(str(content_data_length) + 's')
        content_data = content_format.unpack_from(content_binary_data)
#         print content_data
        #解压缩数据
        contentStr = zlib.decompress(content_data[0])
#         print contentStr
        return self.processData(contentStr, raw_data[2], raw_data[1])
 
    '''
    接收指定长度的数据
    @param length: 数据长度
    '''
    def receiveData(self, length):
        first = True
        data = ""
        while len(data) < length:
            if not first:
                Logger.log('包的长度不够, 需要长度:'+str(length)+', 实际长度:'+str(len(data)), Logger.LOGGER_SOCKET)
                if length == 40:
                    tmp_format = struct.Struct('>%ds'%len(data))
                    tmp_data = tmp_format.unpack_from(data)
                    Logger.log('包的内容:', Logger.LOGGER_SOCKET)
                    Logger.log(tmp_data, Logger.LOGGER_SOCKET, needDec = False)
            first = False
            try:
                extraData = self.client.recv(length - len(data))
            except socket.error, e:
#                 print 'receive:', e
                Logger.log(e.message, Logger.LOGGER_ERROR, True)
                break
            if len(extraData) == 0:
                break
            else:
                data += extraData
        if len(data) < length:
            Logger.log('连接已断开', Logger.LOGGER_SOCKET)
            self.state = SOCKET_STATE_NOT_CONNECTED
        return data
 
    '''
    处理数据
    '''
    def processData(self, contentStr, req, command):
        #     print contentStr
        contentObj = json.loads(contentStr)
        state = contentObj['action']['state']
        #错误
        if state == 0:
            if 'msg' in contentObj['action']['data']:
                Logger.log(contentObj['action']['data']['msg'], output = True)  
        elif state == 1:
            self.doCallback(req, contentObj['action']['data'])
        # 后端推送
        elif state == 3:
#             print contentObj
            self.doPushCallback(command, contentObj['action']['data'])
        #未登录或连接超时
        elif state == 4:
            self.state = SOCKET_STATE_RECONNECTED
            Logger.log('未登录或连接超时', Logger.LOGGER_SOCKET, True)
        #验证码
        elif state == 6:
            Logger.log('被怀疑使用了外挂，程序停止运行', Logger.LOGGER_SOCKET, True)
            self.state = SOCKET_STATE_NOT_CONNECTED
        return state == 1 or state == 3
        
    # 执行请求回调函数
    def doCallback(self, req, data):
        if req in self.callbacks:
            func = self.callbacks.pop(req)
            func(data)
        
    # 后端推送数据处理
    def doPushCallback(self, command, data):
        command = command.replace('\x00', '')
        PushCommand.callback(command, data)

    #是否非连接状态
    def isNotConnected(self):
        return self.state == SOCKET_STATE_NOT_CONNECTED
    
    #是否重连状态
    def isReconnected(self):
        return self.state == SOCKET_STATE_RECONNECTED

#游戏端socket        
gameSocketService = SocketService()
#跨服socket
kfSocketService = None

if __name__ == '__main__':
    print getIp('http://s1.gc.aoshitang.com')